<template>
  <div class="row-table-v4" :style="getTableHeight()" @contextmenu="handleContextMenu">
    <el-auto-resizer>
      <template #default="{ height, width }">
        <el-table-v2
          ref="tableV2Ref"
          :columns="columnList"
          :data="tableData"
          :width="width"
          :height="height"
          :row-height="rowHeight"
          :header-height="rowHeight"
          :row-class="rowClass"
          fixed
          :row-key="rowKey"
          v-model:expanded-row-keys="expandedRowKeys"
          :expand-column-key="expandColumnKey"
          :default-expanded-row-keys="defaultExpandedRowKeys"
        >
        </el-table-v2>
      </template>
    </el-auto-resizer>
    <div class="btn-list">
      <div class="btns">
        <slot name="btnsAdd" v-if="checkedCities.length === 0 && !props.isPreview"></slot>
        <span class="sele-total" v-if="checkedCities.length !== 0 && !props.isPreview">已选数据：{{ alltableList.length }}条</span>
        <slot name="btns" v-if="checkedCities.length !== 0 && !props.isPreview"></slot>
      </div>
      <slot name="total"></slot>
    </div>
  </div>
</template>

<script setup lang="jsx">
import { ref, nextTick, reactive, watch, unref, computed, defineSlots, defineProps } from 'vue'
import { deepClone, getArrayLength } from 'utils/index'
import { isFunction,isArray } from 'utils/validate'
import { ElCheckbox, ElInput, ElCascader, TableV2FixedDir } from 'element-plus'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const tableData = ref([])
const rowKey = ref('index')
const expandedRowKeys = ref([])
const defaultExpandedRowKeys = ref([])
const expandColumnKey = ref('index')
const slots = defineSlots()
const props = defineProps({
  showIndex: {
    type: Boolean,
    default: false
  },
  checkbox: {
    type: Boolean,
    default: false
  },
  showActionBtn: {
    type: Boolean,
    default: false
  },
  isPurchaser: {
    type: Boolean,
    default: true
  },
  isPreview: {
    type: Boolean,
    default: false
  },
  tableActionWidth: {
    type: Number,
    default: 200
  },
  currencyInfo: {
    type: Object,
    default: () => {}
  },
  columnL: {
    type: Array,
    default: () => []
  },
  tableList: {
    type: Array,
    default: () => []
  },
  selectList: {
    type: Array,
    default: () => []
  },
  // 是否多选
  selection: {
    type: Boolean,
    default: false
  },
  isPurchaser: {
    type: Boolean,
    default: true
  },
  model: {
    // 字段模式：1-物料，2-报价
    type: Array,
    default: () => [1]
  }
})
const $emit = defineEmits(['update:selectList', 'update:tableList'])
const checkedCities = ref([])
const isIndeterminate = ref()
// Reflect.has 判断一个对象是否存在某个属性
const getSlot = (slots, slot = 'default', data) => {
  if (!slots || !Reflect.has(slots, slot)) {
    return null
  }
  if (!isFunction(slots[slot])) {
    console.error(`${slot} is not a function!`)
    return null
  }
  const slotFn = slots[slot]
  if (!slotFn) return null
  return slotFn(data)
}
const rowClass = ({ rowData }) => {
  if (rowData.NoValid === false) {
    return 'bg-red-100'
  }
  return ''
}
// 表格当前行操作
const SelectionCell = ({ value, intermediate = false, onChange, disabled }) => {
  return <ElCheckbox onChange={onChange} modelValue={value} indeterminate={intermediate} disabled={disabled} />
}
const InputCell = ({ value, onChange, forwardRef, onBlur, disabled }) => {
  return (
    <ElInput ref={forwardRef} placeholder={'请输入'} style="width: 100%" disabled={disabled} onInput={onChange} modelValue={value} onBlur={onBlur} />
  )
}
const CascaderCall = ({ value, onChange, disabled }) => {
  return <ZcbCascader modelValue={value} onChange={onChange} disabled={disabled}></ZcbCascader>
}

const forEdit = (tableData, rowData, rowIndex) => {
  tableData.map((item) => {
    item.editing = false
    if (item.hasOwnProperty('children') && item.children?.length) {
      forEdit(item.children, rowData, rowIndex)
    }
  })
}
const onKeyup = (event) => {
  return (event.currentTarget.value = event.currentTarget.value.replace(/[^\d.]|^[0]+[0-9]+$|^\.+$/g, ''))
}
const forDom = (rowData, column, onInputChange, onBlur, lovChange, onComplete, cascaderChange) => {
  const input = ref()
  const setRef = (el) => {
    input.value = el
  }
  if (column.disabled) {
    let text = getCodeName(column, rowData) || ''
    let isShowTips =
      text.length > 12 ? (
        <ElTooltip content={text} effect="light">
          <span>{text}</span>
        </ElTooltip>
      ) : (
        text
      )
    return <div class={'tablebg'}>{isShowTips}</div>
  }
  // visiblePurchaser 采方维度：0-不可视，1-仅可视，2-可视非必填，3-可视且必填
  // visibleVendor  供方维度：0-不可视，1-仅可视，2-可视非必填，3-可视且必填

  if (column.presetFlag) {
    // 判断字段类型 展示不同的组件 数据类型：1-数字，2-金额，3-文本，4-公式，5-字段拼接
    if (column.dataType === 3) {
      if (column.key === 'materialCatalog') {
        return <CascaderCall value={rowData[column.code]} disabled={column.disabled} onChange={cascaderChange}></CascaderCall>
      } else if (column.key === 'unit') {
        column.config.allSelectList = rowData[column.code]
        return <lovView modelValue={rowData[column.code]} lovViewConfig={column.config} onLovChange={lovChange} disabled={column.disabled}></lovView>
      } else if (column.key === 'attachment') {
        return (
          <zcbUpload
            value={rowData[column.code + 'List']}
            fieldSceneVo={column.config.fieldSceneVo}
            fileSize={column.config.fileSize}
            fileType={column.config.fileType}
            isTableUpload={column.config.isTableUpload}
            isDownload={column.config.isDownload}
            isShowBtn={isArray(rowData[column.code + 'List']) && rowData[column.code + 'List'].length > 0 ? false : true}
            disabled={column.disabled}
            onOnComplete={onComplete}
          ></zcbUpload>
        )
      } else {
        return <InputCell forwardRef={setRef} value={rowData[column.code]} onChange={onInputChange} onBlur={onBlur} disabled={column.disabled} />
      }
    } else if (column.dataType === 2) {
      // column.dataType === 1 &&
      // 数量
      return (
        <InputCell
          forwardRef={setRef}
          value={rowData[column.code]}
          onKeyup={onKeyup}
          onChange={onInputChange}
          onBlur={onBlur}
          disabled={column.disabled}
        />
      )
    } else if (column.dataType === 1) {
      if (column.key === 'taxRate') {
        column.config.allSelectList = rowData['taxRateObj']
        column.config.taxRateCodeValue = rowData['taxRateCode']
        return (
          <lovView
            modelValue={rowData[column.code + 'Obj']}
            lovViewConfig={column.config}
            onLovChange={onChange}
            disabled={column.disabled}
          ></lovView>
        )
      } else {
        return (
          <InputCell
            forwardRef={setRef}
            value={rowData[column.code]}
            onKeyup={onKeyup}
            onChange={onInputChange}
            onBlur={onBlur}
            disabled={column.disabled}
          />
        )
      }
    } else {
      return (
        <InputCell
          forwardRef={setRef}
          value={rowData[column.code]}
          onKeyup={onKeyup}
          onChange={onInputChange}
          onBlur={onBlur}
          disabled={column.disabled}
        />
      )
    }
  } else {
    return (
      <InputCell
        forwardRef={setRef}
        value={rowData.extendMap && rowData.extendMap[column.code] ? rowData.extendMap[column.code].content : rowData[column.code] || ''}
        onKeyup={column.dataType === 1 || column.dataType === 2 ? onKeyup : ''}
        onChange={onInputChange}
        onBlur={onBlur}
        disabled={column.disabled}
      />
    )
  }
}
// 处理右键点击事件的逻辑
const handleContextMenu = (event) => {
  event.preventDefault()
  forEdit(tableData.value)
}
const alltableList = ref([]) //  tableData 大平成一级 总共的条数
watch(
  () => props.tableList,
  (newValue, oldValue) => {
    //  只有当数据长度发生变化时才进行初始化数据，避免重复执行
    // if (!oldValue || getArrayLength(newValue) != getArrayLength(tableData.value)) {
    //   nextTick(() => {
    //     alltableList.value = []
    //     initData()
    //   })
    // }
    nextTick(() => {
      alltableList.value = []
      initData()
    })
  },
  { immediate: true, deep: true }
)

const rowHeight = ref(48)
const getTableHeight = () => {
  const rowCount = alltableList.value.length // 总行数，根据实际情况修改
  const tableHeight = rowCount > 10 ? '540' : rowCount == 0 ? '400' : rowHeight.value * (rowCount + 1) // 计算表格的总高度
  return `height: ${tableHeight}px`
}
watch(
  () => props.selectList,
  (newValue, oldValue) => {
    //  只有当数据长度发生变化时才进行初始化数据，避免重复执行
    if (!oldValue || getArrayLength(newValue) != getArrayLength(tableData.value)) {
      nextTick(() => {
        checkedCities.value = newValue || []
      })
    }
  },
  { immediate: true, deep: true }
)

const initColumn = ref([])
const initColumnFalg = ref(true)
const extendMap = ref({})
const setinitColumnextendMap = () => {
  initColumn.value.map((item) => {
    extendMap.value[item.code] = {
      type: '',
      dataType: item.dataType,
      code: item.code, // 静态值集或值集视图的集合ID（传给后端参数
      content: '',
      section: '' // 字段域code
    }
  })
  return extendMap
}
//初始化数据
const initData = () => {
  $emit('update:selectList', [])
  tableData.value = props.tableList && props.tableList.length > 0 ? recursiveData(deepClone(props.tableList || [])) : []
  console.log(tableData.value)
}
const recursiveData = (data, parentIndex, parentRowIndex) => {
  data.map((item, index, arr) => {
    alltableList.value.push(item)
    // item['materialCatalog'] = item['materialCatalogId'].length > 0 ? item['materialCatalogId'][item['materialCatalogId'].length] : []
    // item['materialCatalog'] = item['materialCatalog'] ? item['materialCatalog'] : []
    item['lastFlag'] = '' // 是否是最后一级
    item['children'] = item['children'] && item['children'].length > 0 ? item['children'] : []
    item['rowIndex'] ? '' : (item['checked'] = false)
    item['index'] = parentIndex ? `${parentIndex}-${index + 1}` : (index + 1).toString()
    item['serialNumber'] = item['index']
    item['level'] = item['index'].split('-').length
    item['sortNum'] = index + 1
    item['rowIndex'] = parentRowIndex ? `${parentRowIndex}-${index}` : index.toString()
    if (!item.hasOwnProperty('NoValid')) {
      item['NoValid'] = true
    }
    if (!item.hasOwnProperty('extendMap')) {
      item['extendMap'] = extendMap.value
    }
    // item['editing'] = tableData.value.length === 1 && item?.children?.length === 0 ? true : false
    item['editing'] = item['editing'] || false
    expandedRowKeys.value.push(item['index'])

    if (item.hasOwnProperty('children') && item.children.length == 0) {
      item['lastFlag'] = 'TRUE'
    }
    if (item.children) recursiveData(item.children, item['index'], item['rowIndex'])
  })
  return data
}
// 通知更新数据
const updateData = () => {
  $emit('update:tableList', deepClone(tableData.value))
}
//初始化表格列
const columnList = computed(() => {
  return updateColumns()
})

const traverseTree = (nodes, value) => {
  nodes.forEach((node) => {
    value ? checkedCities.value.push(node) : ''
    node.checked = value
    if (node.children && node.children.length > 0) {
      traverseTree(node.children, value)
    }
  })
}

const updateColumns = () => {
  let arr = []
  // seqNum 排序
  // 字段模式：1-物料，2-报价
  let columnL =
    props.columnL.length > 0
      ? props.columnL
          .filter(
            (item) => props.model.includes(item.model) && item.visibleFlag && item[props.isPurchaser ? 'visiblePurchaser' : 'visibleVendor'] > 0
          )
          .sort((a, b) => a.seqNum - b.seqNum)
      : []

  initColumn.value = columnL
  initColumn.value = initColumn.value.filter((item) => !item.presetFlag)
  if (initColumn.value.length > 0 && initColumnFalg.value && tableData.value.length > 0) {
    setinitColumnextendMap()
    initData()
    initColumnFalg.value = false
    updateData()
  }

  columnL.forEach((item) => {
    // visiblePurchaser 采方维度：0-不可视，1-仅可视，2-可视非必填，3-可视且必填
    // visibleVendor 供方维度：0-不可视，1-仅可视，2-可视非必填，3-可视且必填
    item.disabled = item[props.isPurchaser ? 'visiblePurchaser' : 'visibleVendor'] == 1 ? true : false
    item.config = {}
    if (item.code == 'unit') {
      item.config = {
        lovViewCode: 'ZEMD.TENANT_UNIT_VIEW',
        keyId: 'unitId', // 多选根据id选择  默认key id
        allSelectList: []
      }
    } else if (item.code == 'taxRate') {
      item.config = {
        lovViewCode: 'ZEMD.TAX_RATE_VIEW',
        keyId: 'taxRateCode', // 多选根据id选择  默认key id
        allSelectList: []
      }
    } else if (item.code == 'attachment') {
      item.config = {
        fieldSceneVo: {
          moduleCode: 'sourcing',
          sceneCode: 'sourcing_single'
        },
        fileSize: 100,
        fileType: ['jpg', 'png', 'gif', 'jpeg', 'JPG', 'PNG', 'GIF', 'JPEG'],
        limit: 1,
        isTableUpload: true,
        isDownload: true,
        isShowBtn: true
      }
    }

    // 字段是否可编辑修改
    let widthC = 180
    // 动态设置列宽
    if (document.querySelector('.el-table-v2')?.offsetWidth / widthC >= columnL.length) {
      let cW = props.showIndex ? 50 : 0
      let iW = props.checkbox ? 50 : 0
      let aW = props.showActionBtn ? parseInt(props.tableActionWidth) : 0
      widthC = (document.querySelector('.el-table-v2')?.offsetWidth - cW - iW - aW) / columnL.length
    }
    arr.push({
      ...item,
      key: `${item.code}`,
      dataKey: `${item.code}`,
      width: widthC,
      cellRenderer: (res) => {
        let { cellData, column, rowIndex, rowData, columnIndex } = res
        // 判断是否有插槽
        let isSlot = getSlot(slots, column.key, { scope: rowData, index: rowIndex, $index: rowIndex, column: column })

        const onEnterEditMode = () => {
          forEdit(tableData.value, rowData, rowIndex)
          rowData.editing = true
        }

        const onInputChange = (value) => {
          if (!column.presetFlag) {
            // if (rowData.hasOwnProperty('extendMap')) {
            //   rowData.extendMap[column.code] = {
            //     type: '',
            //     dataType: column.dataType,
            //     code: column.code, // 静态值集或值集视图的集合ID（传给后端参数
            //     content: value,
            //     section: '' // 字段域code
            //   }
            // } else {
            //   rowData.extendMap = {}
            //   rowData.extendMap[column.code] = {
            //     type: '',
            //     dataType: column.dataType,
            //     code: '', // 静态值集或值集视图的集合ID（传给后端参数
            //     content: value,
            //     section: '' // 字段域code
            //   }
            // }
            rowData.extendMap[column.code] = {
              type: '',
              dataType: column.dataType,
              code: column.code, // 静态值集或值集视图的集合ID（传给后端参数
              content: value,
              section: '' // 字段域code
            }
          } else {
            rowData[column.code] = value
          }
          // updateData()
        }
        const onBlur = () => {
          updateData()
        }
        const lovChange = (res, fileList) => {
          if (column.code === 'taxRate') {
            rowData[column.code] = res?.taxRateNum
            rowData[column.code + 'Code'] = res?.taxRateCode
            rowData[column.code + 'Obj'] = res?.taxRateCode
              ? {
                  taxRate: res?.taxRateNum || '',
                  taxRateNum: res?.taxRateNum || '',
                  taxRateCode: res?.taxRateCode || ''
                }
              : null
          } else {
            rowData[column.code] = res
          }
          updateData()
        }
        const cascaderChange = (res) => {
          rowData.materialCatalogId = res.ids
          rowData.materialCatalog = res.ids[res.ids.length - 1]
          let arr = res.items.map((item, index) => {
            return item.categoryName
          })
          rowData.materialCatalogName = arr.join('>')
          updateData()
        }
        //  上传附件
        const onComplete = (val, valueContent) => {
          rowData[column.code] = val
          rowData[column.code + 'List'] = valueContent
          updateData()
        }

        let text = getCodeName(column, rowData) || ''
        let isShowTips =
          text.length > 12 ? (
            <ElTooltip content={text} effect="light">
              <span>{text}</span>
            </ElTooltip>
          ) : (
            text
          )
        return isSlot ? (
          <div class={'table-v2-inline-editing-trigger' + (column.disabled ? 'tablebg' : '')}>
            {getSlot(slots, column.key, { scope: rowData, index: rowIndex, $index: rowIndex, column: column })}
          </div>
        ) : props.isPreview || !rowData.editing || (rowData.level % 2 !== 0 && !column.splitFlag && rowData.children.length > 0) ? (
          <div
            class={
              res.class +
              (props.isPreview ? '' : ' table-v2-inline-editing-trigger') +
              (!props.isPreview && ((rowData.level === 1 && !column.splitFlag && rowData.children.length > 0) || column.disabled) ? ' tablebg' : '')
            }
            onClick={onEnterEditMode}
          >
            {isShowTips}
          </div>
        ) : (
          forDom(rowData, column, onInputChange, onBlur, lovChange, onComplete, cascaderChange)
        )

        // return (rowData.editing && !column.disabled) || (rowData.level > 1 && column.splitFlag) ? (
        //   forDom(rowData, column, onInputChange, onBlur, onChange)
        // ) : (
        //   <div class={res.class + (!column.disabled  ? ' table-v2-inline-editing-trigger' : '')} onClick={onEnterEditMode}>
        //     {(column.code === 'unit' && rowData[column.code] && Object.keys(rowData[column.code]).length !== 0) ? rowData[column.code][`${column.code}Name`] :
        //     (column.code === 'attachment' && rowData[column.code] && isArray(rowData[column.code]) && rowData[column.code].length  > 0) ? rowData[column.code][0].fileName :
        //     (column.code === 'materialCatalog' && rowData[`${column.code}Name`]) ? rowData[`${column.code}Name`] :
        //     rowData[column.code]  ? rowData[column.code] : '--'}
        //   </div>
        // )
      },
      headerCellRenderer: (res) => {
        let { cellData, column, columns, rowIndex, rowData, columnIndex } = res
        // expandColumnKey.value = columns[0].index;
        return (
          <span class={props.checkbox ? 'bor-l table-head-title' : 'table-head-title'} style="width: 180px">
            {column[props.isPurchaser ? 'visiblePurchaser' : 'visibleVendor'] == 3 ? <i class="color_danger">*</i> : ''}
            {column.name}
          </span>
        )
      }
    })
  })
  arr.unshift({
    key: 'index',
    width: 100,
    title: t('keys.serial_no'),
    cellRenderer: ({ rowData }) => `${rowData.index}`
  })
  if (!props.isPreview) {
    if (props.selection) {
      arr.unshift({
        key: 'selection',
        width: 50,
        align: 'center',
        cellRenderer: ({ rowData }) => {
          const onChange = (value) => {
            rowData.checked = value
            if (value) {
              let isGet = checkedCities.value.find((item) => item == rowData)
              if (!isGet) {
                checkedCities.value.push(rowData)
              }
            } else {
              checkedCities.value = checkedCities.value.filter((item) => {
                return item !== rowData
              })
            }
            $emit('update:selectList', checkedCities.value)
          }
          return <SelectionCell value={rowData.checked} onChange={onChange} />
        },

        headerCellRenderer: () => {
          const onChange = (value) => {
            if (value) {
              checkedCities.value = []
              traverseTree(tableData.value, value)
            } else {
              checkedCities.value = []
              traverseTree(tableData.value, value)
            }
            $emit('update:selectList', checkedCities.value)
          }
          const allSelected = alltableList.value.length > 0 && checkedCities.value.length == alltableList.value.length ? true : false
          isIndeterminate.value =
            alltableList.value.length && checkedCities.value.length > 0 && checkedCities.value.length != alltableList.value.length ? true : false
          return <SelectionCell value={allSelected} intermediate={isIndeterminate.value} onChange={onChange} />
        }
      })
    }
    if (props.showActionBtn) {
      arr.push({
        key: 'actionBtn',
        width: parseInt(props.tableActionWidth),
        title: '操作',
        fixed: TableV2FixedDir.RIGHT,
        cellRenderer: (res) => {
          let { cellData, column, rowIndex, rowData, columnIndex } = res
          let isSlot = getSlot(slots, column.key, {
            scope: rowData,
            index: rowIndex,
            $index: rowIndex,
            column: column,
            res
          })
          return isSlot ? (
            <div class={res.class}>
              {slots[column.key]?.({
                scope: rowData,
                index: rowData.index,
                $index: rowIndex,
                column: column,
                res
              })}
            </div>
          ) : (
            ''
          )
        }
      })
    }
  }
  return arr
}

// 字段name 回显处理
const getCodeName = (column, rowData) => {
  let name = ''
  if (column.presetFlag) {
    if (column.code === 'unit' && rowData[column.code] && rowData[column.code] !== '') {
      name = rowData[column.code][`${column.code}Name`]
    } else if (column.code === 'attachment' && rowData[column.code] && isArray(rowData[column.code]) && rowData[column.code].length > 0) {
      name = rowData[column.code][0].fileName
    } else if (column.code === 'materialCatalog' && rowData[`${column.code}Name`]) {
      name = rowData[`${column.code}Name`]
    } else if (rowData[column.code] || props.isPreview) {
      name = rowData[column.code]
    }
  } else {
    // 自定义字段
    name = rowData.extendMap && rowData.extendMap[column.code] ? rowData.extendMap[column.code].content : ''
  }
  return name
}
</script>

<style lang="scss">
$table-border: #e5e6eb;
$table-bacground: #fafbfc;
.row-table-v4 {
  padding-bottom: 44px;
  .el-auto-resizer {
    border: 1px solid $table-border;
  }
  .el-table-v2 {
    .el-table-v2__main {
      .el-table-v2__header-cell {
        border-right: 1px solid $table-border;
        background: $table-bacground;
        .table-head-title {
          font-size: 14px;
          &:last-child {
            border-right: 0;
          }
          .color_danger {
            color: var(--el-color-danger);
            padding-right: 4px;
          }
        }
      }
    }
    .el-table-v2__row {
      .el-table-v2__row-cell {
        // :nth-child(1) {
        // }
        .el-icon.el-table-v2__expand-icon {
          margin-inline-start: 0px !important;
        }
        .table-v2-inline-editing-trigger {
          border: 1px transparent dotted;
          padding: 0 11px;
          height: 28px;
          line-height: 26px;
          box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-border-color)) inset;
          width: 100%;
          &:hover {
            border-color: var(--el-color-primary);
          }
        }
        .tablebg {
          background: #f2f3f5 !important;
          padding: 0 11px;
          height: 28px;
          line-height: 26px;
          width: 100%;
          // box-shadow: none !important;
        }
        .el-button.el-button--primary.is-link {
          color: #0066ff;
          line-height: 22px;
          &:active {
            color: #0066ff;
          }
        }
        .el-input {
          --el-input-height: 30px;
        }
      }
    }
  }

  .btn-list {
    padding: 8px 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    .btns {
      display: flex;
      align-items: center;
      .sele-total {
        font-size: 14px;
        font-weight: 400;
        color: #4e5969;
        line-height: 22px;
        display: flex;
        align-items: center;
        &::after {
          content: '';
          width: 1px;
          height: 12px;
          background: #e5e6eb;
          margin: 0 16px;
        }
      }
    }
    // 金额底部汇总样式
    .total_amount {
      font-size: var(--el-menu-item-font-size);
      padding: 0;
      text-align: right;
      .info {
        font-size: var(--el-menu-item-font-size);
        color: var(--el-color-primary);
      }
    }
    .el-button.is-link {
      color: #0066ff;
      line-height: 22px;
      &:active {
        color: #0066ff;
      }
    }
  }
}
</style>
